#include<iostream>
#include<cstring>
#include<fstream>
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<vector>
#include<direct.h>
using namespace std;
void setCommondStyle() {
	system("title LOGIN_SYSTEM");
	system("color f0");
	//system("mode con cols=40 lines=8");
}
/*————————————————
版权声明：本文为CSDN博主「王世晖」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
原文链接：https://blog.csdn.net/wangshihui512/article/details/8921926*/

int CountLines(string filename) //行数计算
{
	ifstream ReadFile;
	int n = 0;
	string tmp;
	ReadFile.open(filename.c_str());//ios::in 表示以只读的方式读取文件
	if (ReadFile.fail())//文件打开失败:返回0
	{
		return 0;
	}
	else//文件存在
	{
		while (getline(ReadFile, tmp, '\n'))
		{
			n++;
		}
		ReadFile.close();
		return n;
	}
}

string ReadLine(string filename, int line) //读取特定的某一列
{
	int lines, i = 0;
	string temp;
	fstream file;
	file.open(filename.c_str());
	lines = CountLines(filename);

	if (line <= 0)
	{
		return "Error 1: 行数错误，不能为0或负数。";
	}
	if (file.fail())
	{
		return "Error 2: 文件不存在。";
	}
	if (line > lines)
	{
		return "Error 3: 行数超出文件长度。";
	}
	while (getline(file, temp) && i < line - 1)
	{
		i++;
	}
	file.close();
	return temp;
}
void pathConvert_Single2Double(string& s){
	string::size_type pos = 0;
	while ((pos = s.find('\\', pos)) != string::npos){
		s.insert(pos, "\\");
		pos = pos + 2;
	}
}
string getaddress(){
    char *buffer;
    if((buffer=getcwd(NULL,0))==NULL){
        perror("getcwd error!");
    }
    else{
        string bf=buffer;
        pathConvert_Single2Double(bf);
        return bf;
        free(buffer);
        system("pause");
    }
}
string getaddress_withoutdouble(){
    char *buffer;
    if((buffer=getcwd(NULL,0))==NULL){
        perror("getcwd error!");
    }
    else{
        string bf=buffer;
        //pathConvert_Single2Double(bf);
        return bf;
        free(buffer);
        system("pause");
    }
}
/*————————————————
版权声明：本文为CSDN博主「努力的袁」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
原文链接：https://blog.csdn.net/qq_44747572/article/details/121436815*/
void create_db(string username){
    string dbname;
    dbname=getaddress_withoutdouble()+"/"+username;
    string command;
    command="mkdir -p "+dbname;
    system("command");
    
}
int main(){
    char db_all[10000],db_usr[10000]={},db_pwd[10000]={},buffer[10000],db_num[10000]={},username[10000],password[10000],n_usr[10000]={},n_pwd[10000]={},again_n_pwd[10000]={},n_num[10000]={},n_all[10000]={},key,create_usr[10000]={},key_word_0[10000]="admin",key_word_1[10000]={};
    int length=0,temp=1,ch_temp=0,m=0,n=0,coun=0,leng_num=0,leng_usr=0,leng_pwd=0,step=0,key_coun=0;
    bool cmp_usr=false,cmp_pwd=false,cmp;
    string filename="C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\database.txt";
    fstream db ("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\database.txt");
    fstream db_d ("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\database.txt");
    fstream couner ("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\c_database.txt");
    couner>>coun;
    //couner.close();
    setCommondStyle();
    cout<<"Please enter your username(if you want to sign up,please enter sign):";
    cin>>username;
    if(username[0]=='s'&&username[1]=='i'&&username[2]=='g'&&username[3]=='n'){ //判断是否注册
        fstream db_in ("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\database.txt",ios::app); //如果注册，则读取数据库
        couner>>coun; //读取当前序数
        couner.close(); 
        cout<<"Please enter the username that you want to create:";
        cin>>n_usr; //获取新建账户名称
        int key_word_count = 0; 
        for(int i=0;i<strlen(n_usr);i++){ //判断用户名是否符合要求
            if(n_usr[i]==key_word_0[i]){
                key_word_count++;
            }
        }
        if(key_word_count==strlen(n_usr)){ //如果出现admin关键词，则退出
            cout<<"this is an admin account,you can't create it!"<<endl;
            main();
        }
        while(!db_d.eof()){ //判断账户名是否被占用
            int sum = 0;
            db_d>>db_all; //在db_all里面写入数据库中的一行（循环进行）
            length=strlen(db_all); //得到该行的长度
            memset(create_usr,0,sizeof(create_usr));
            int i=0,m=0,n=0;
            for(i=0;i<length;i++){ //查询该行中$符号的位置
                if(db_all[i]!='$') continue;
                if(db_all[i]=='$' &&m==0) m=i;
                else n=i;
            }
            int j=0;
            for(int i=m+1,j=0;i<n;i++) //得到该行数据中账户名
                create_usr[j++]=db_all[i];
            for(int i=0;i<strlen(n_usr);i++){ //计算该用户名与用户输入的用户名之间的相似度
                if(n_usr[i]==create_usr[i]){
                    sum++;
                }
            }
            if(sum==strlen(n_usr)){ //若完全相似，则提示已被占用
                cout<<"ERROR! This username was occupied!"<<endl;
                system("pause");
                main();
            }
            else;
        }
        
        /*判断用户名是否重复*/
        cout<<"Please enter your password:"; //若用户名全部符合要求，则开始要求用户输入密码
        while((key=_getch())!='\r'){ //实现密码隐藏
            n_pwd[key_coun++]=key;
            putchar('*');
        }
        cout<<endl;
        cout<<"please enter your password again:";
        while((key=_getch())!='\r'){ //实现密码隐藏
            again_n_pwd[key_coun++]=key;
            putchar('*');
        }
        cout<<endl;
        int n_pwd_again_sum=0;
        for(int i=0;i<strlen(n_pwd);i++){
            if(n_pwd[i]==again_n_pwd[i]){
                n_pwd_again_sum++;
            }
        }
        if(n_pwd_again_sum!=strlen(n_pwd)){ //判断两次输入的密码是否完全相同
            cout<<"ERROR! The passwords that you enter twice are different!"<<endl;
            main();
        }
        itoa(coun+1,n_num,10); //转换一个读取到的序号（整形）为char
        leng_num=strlen(n_num); //获取转换到的序号的长度
        for(int i=0;i<leng_num;i++) //按照序号长度编写新的一行的第一部分内容
            n_all[i]=n_num[i];
        n_all[leng_num]='$';
        step=leng_num+1; //第二部分的起始位置（第一部分的终止位置+1）
        leng_usr=strlen(n_usr); //获取新建的用户名长度
        leng_pwd=strlen(n_pwd); //获取新建的密码长度
        for(int i=step,j=0;i<leng_usr+step;i++,j++) //将新建的用户名写入
            n_all[i]=n_usr[j];
        step=step+leng_usr+1; //第三部分的起始位置（第二部分的终止位置+1）
        n_all[step-1]='$'; 
        for(int i=step,j=0;i<leng_pwd+step;i++,j++) //将新建的密码写入
            n_all[i]=n_pwd[j];
        db_in<<n_all<<endl; //将新建的用户信息（字符串）写入到数据库中
        db_in.close(); //关闭数据库接口
        fstream c_couner("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\c_database.txt",ios_base::out); //清空序号库
        coun++; //序号自增1
        c_couner<<coun; //写入序号 
        c_couner.close(); //关闭序号库
        create_db(n_usr);
        cout<<"This user was created successfully!"<<endl; //提示
        system("pause");
        main();
    }
    else{ //如果正常输入了账号，则进行下一步
        cout<<"Please enter your password:";  
        while((key=_getch())!='\r'){ //实现密码隐藏
            password[key_coun++]=key;
            putchar('*');
        }
        cout<<endl;
        while(!db.eof()){ //开始在数据库中寻找符合该条件（账号密码）的项
            cmp_usr=false,cmp_pwd=false;
            db>>db_all; //读取数据库中一行
            length=strlen(db_all); //获得该行的长度
            memset(db_num,0,sizeof(db_num)); //初始化
            memset(db_usr,0,sizeof(db_usr)); //初始化
            memset(db_pwd,0,sizeof(db_pwd)); //初始化
            int i=0,m=0,n=0; 
            for(i=0;i<length;i++){ //查找两个$的位置，记作m、n
                if(db_all[i]!='$') continue; 
                if(db_all[i]=='$' &&m==0) m=i;
                else n=i;
            }
            int j=0; //定义循环变量
            for(int i=0;i<m;i++) //得到分离后的编号（从0到第一个$）
                db_num[j++]=db_all[i];
            for(int i=m+1,j=0;i<n;i++) //得到分离后的账号（从第一个$+1到第二个$）
                db_usr[j++]=db_all[i];
            for(int i=n+1,j=0;i<length;i++) //得到分离后的密码（从第二个$+1到结尾）
                db_pwd[j++]=db_all[i];
            int usr_sum=0,pwd_sum=0; //判断变量
            for(int i=0;i<strlen(db_usr);i++) //判断账号是否准确，准确则判断变量自增
                if(username[i]==db_usr[i])
                    usr_sum++;
            for(int i=0;i<strlen(db_pwd);i++){ //判断密码是否同时均准确，准确则判断变量自增
                if(password[i]==db_pwd[i])
                    pwd_sum++;
            }
            if(usr_sum==strlen(db_usr)) //若账号判断变量得值正确，则改变布尔值
                cmp_usr=true;
            if(pwd_sum==strlen(db_pwd)) //若密码判断变量得值正确，则改变布尔值
                cmp_pwd=true;
            if(cmp_usr&&cmp_pwd){ //若两个布尔值均为真，则改变全局判断变量，并且跳出循环
                cmp=true;
                break;
            }
        }
        if(cmp){ //当确认账号密码正确
            char ad[10000]={'a','d','m','i','n'}; //关键字
            int admin_sum=0; //关键字重合总数
            cout<<"WELCOME!"<<endl; 
            for(int i=0;i<strlen(username);i++){ //判断用户名是否与关键字admin重合
                if(username[i]==ad[i]){
                    admin_sum++;
                }
            }
            if(admin_sum==strlen(username)){ //若重合率为完全重合，则判断该用户为管理员用户
                //char fln[10000]="C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\database.txt";
                char in[10000]; //输入值
                //int into=0;
                int line=CountLines(filename); //获取数据库总行数（即总用户数）
                cout<<"WEICOME TO THE ADMIN CONTROL PANEL!"<<endl;
                cout<<"if you want to delete a user,please enter 'del'"<<endl<<"If you want to see all the users,please enter list"<<endl;
                LOOP:cout<<"Please enter:"; //设置循环点
                cin>>in;
                //itoa(into,in,10);
                if(in[0]=='d'&&in[1]=='e'&&in[2]=='l'){ //若管理员意向删除某用户
                    cout<<"If you want to delete a user,please enter the user's ID:";
                    /*管理员模块实现,借助CSDN*/
                    char del_unum[10000]={},create_num[10000]={},del_sth[10000]={}; //分别为：所转换得到的ID、从数据库中读取的ID、要删除的整行内容
                    int del_sum=0,line_sum=1,into;  //分别为：用户输入的数据与数据库中的内容的重合率、要删除的行的物理计数、用户输入的要删除的用户ID（整形）
                    string tmp,line_getstr; //分别为：要删除的整行、从数据库中读取到的整行
                    cin>>into; //得到要删除的ID
                    itoa(into,del_unum,10); //转换ID为字符型
                    if(into==1){ //判断该ID是否不符合要求
                        cout<<"ERROR! This is a admin user!"<<endl;
                        goto LOOP; 
                    }
                    else;
                    fstream db_dou ("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\database.txt");//读取数据库
                    fstream db_double ("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\database.txt"); //读取数据库
                    fstream db_temp ("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\temp_db.txt",ios_base::out); //读取临时数据库
                    while(!db_dou.eof()){ //循环直到遇到文件尾
                        //int sum = 0; 
                        db_dou>>db_all; //读取数据库中的一行
                        length=strlen(db_all); //获得该行的长度
                        memset(create_num,0,sizeof(create_num)); //初始化
                        int i=0,m=0,n=0;
                        for(i=0;i<length;i++){ //获取两个$的位置记作m、n
                            if(db_all[i]!='$') continue;
                            if(db_all[i]=='$' &&m==0) m=i;
                            else n=i;
                        }
                        int j=0;
                        for(int i=0;i<n;i++) //得到分离后的ID
                            create_num[i]=db_all[i];
                        for(int i=0;i<strlen(del_unum);i++){ //判断要删除的ID是否与后方重合
                            if(del_unum[i]==create_num[i]){
                                del_sum++;
                            }
                        }
                        if(del_sum==strlen(del_unum)){ //若重合
                            tmp=ReadLine(filename,line_sum); //读取要删除的整行
                            for(int i=0;i<line;i++){ 
                                db_double>>line_getstr; //写入进临时变量
                                if(line_getstr==tmp||line_getstr==""){ //如果遇到文件尾或要删除的整行则跳过
                                    continue;
                                }
                                else{
                                    db_temp<<line_getstr<<endl; //否则正常写入临时数据库
                                }
                            }
                            //cout<<tmp;
                            break; //执行完成，跳出循环
                        }
                        else;
                        line_sum++;
                    }
                    db_dou.close(); //关闭数据库接口
                    db_double.close(); //关闭数据库接口
                    db_temp.close(); //关闭临时数据库接口
                    fstream db_t ("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\temp_db.txt"); //读取临时数据库
                    fstream db_new("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\database.txt",ios_base::out); //完全删除数据库内的全部内容
                    char temp_data[10000];
                    for(int i=0;i<line-1;i++){ //写入数据库
                        db_t>>temp_data;
                        db_new<<temp_data<<endl;
                    }
                    db_new.close(); //关闭数据库接口
                    db_t.close(); //关闭数据库接口 
                    fstream db_ne("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\temp_db.txt",ios_base::out);//清空临时数据库
                    db_new.close(); //关闭数据库接口
                    cout<<"This user was deleted successfully!"<<endl; //提示
                    goto LOOP; //返回
                }
                else if(in[0]=='l'&&in[1]=='i'&&in[2]=='s'&&in[3]=='t'){
                    fstream db_list("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\database.txt");
                    char data_list[10000];
                    for(int i=0;i<CountLines(filename);i++){
                        db_list>>data_list;
                        cout<<data_list<<endl;
                    }
                    db_list.close();
                    goto LOOP;
                }
                else if(in[0]='n'&&in[1]=='e'&&in[2]=='w'){
                    fstream counter("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\c_database.txt");
                    fstream db_list("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\database.txt",ios::app);
                    char new_user_all[10000]={};
                    int data_number;
                    counter>>data_number;
                    cout<<"We will put all the trust in the admin! Please input normally!"<<endl;
                    cout<<"Now , the next number of the user is "<<data_number+1<<endl;
                    cout<<"Standard form of input is like this: the number of the user$username$password"<<endl;
                    cout<<"So,please enter carefully:";
                    cin>>new_user_all;
                    cout<<"Are you sure that the next line is "<<new_user_all<<" ? If that's right, please enter yes:";
                    int sure=0;
                    cout<<"Are you sure that the text you entered is correct? If no, please enter 1 to break!"<<endl;
                    cout<<"please enter:";
                    cin>>sure;
                    if(sure==1){
                        cout<<"The operation has been canceled!"<<endl;
                        goto LOOP;
                    }
                    db_list<<new_user_all<<endl;
                    counter.close();
                    db_list.close();
                    fstream counter_n ("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\c_database.txt");
                    int nw;
                    counter_n>>nw;
                    nw=nw+1;
                    counter_n.close();
                    fstream counter_t ("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\c_database.txt",ios_base::out);
                    counter_t<<nw;
                    counter_t.close();
                    cout<<"The user was created successfully!"<<endl;
                    //cin>>sure;
                    goto LOOP;
                }
            }
            else{ //普通用户功能
                cout<<"here!"<<endl;
                //normal_users(username);
                cout<<"USING!"<<endl;
                char retry[10000]={},temp_pwd[10000]={},user_in[10000]={},keyword_0[10000]="change",db_all_2[10000]={},temp_user[10000]={};
                int pwd_same=0,keyword_number_0=0,line_number_0=0,length=0,address_0=0;
                string in_str,tmp,filename="C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\database.txt";
                cin>>user_in;
                for(int i=0;i<strlen(user_in);i++){
                    if(user_in[i]==keyword_0[i]){
                        keyword_number_0++;
                    }
                }
                if(keyword_number_0==strlen(user_in)){ //更改密码行为
                    fstream db_n ("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\database.txt");
                    m=0;
                    int sum = 0,same_sum=0;
                    while(!db_n.eof()){
                        //cout<<"ReadFile!"<<endl;
                        address_0++;
                        db_n>>db_all_2;
                        length=strlen(db_all_2);
                        memset(temp_user,0,sizeof(temp_user));
                        memset(temp_pwd,0,sizeof(temp_pwd));
                        int i=0;
                        m=0,n=0;
                        for(i=0;i<length;i++){
                            if(db_all_2[i]!='$') continue;
                            if(db_all_2[i]=='$' &&m==0) m=i;
                            else n=i;
                        }
                        int j=0;
                        for(int i=m+1,j=0;i<n;i++)
                            temp_user[j++]=db_all_2[i];
                        for(int i=n+1,j=0;i<length;i++)
                            temp_pwd[j++]=db_all_2[i];
                        for(i=0;i<strlen(temp_user);i++){
                            if(username[i]==temp_user[i]){
                                same_sum++;
                            }
                        }
                        if(same_sum==strlen(temp_user)){
                            tmp=ReadLine(filename,address_0);
                            cout<<tmp<<endl;
                            string temp_str_db_n=tmp;
                            int j=0,p=0,q=0;
                            m=0;
                            for(j=0;j<strlen(db_all_2);j++){
                                if(db_all_2[j]!='$') continue;
                                if(db_all_2[j]=='$' &&p==0) p=j;
                                else q=j;
                            }
                            cout<<"please enter the password:";
                            cin>>retry;
                            for(j=0;j<strlen(temp_pwd);j++){
                                if(retry[j]==temp_pwd[j]){
                                    pwd_same++;
                                }
                            }
                            if(pwd_same==strlen(temp_pwd)){
                                cout<<"Please enter your new password:";
                                cin>>in_str;
                                tmp.replace(q+1,tmp.length()+1-q,in_str);
                                line_number_0= CountLines(filename);
                                string temp_now_str;
                                fstream db_changelist(filename);
                                fstream db_temp_change("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\c_database.txt",ios_base::out);
                                for(int i=0;i<line_number_0;i++){
                                    db_changelist>>temp_now_str;
                                    if(temp_now_str==temp_str_db_n){
                                        db_temp_change<<tmp<<endl;
                                    }
                                    else{
                                        db_temp_change<<temp_now_str<<endl;
                                    }
                                }
                                db_changelist.close();
                                db_temp_change.close();
                                fstream db_new_change_pwd (filename,ios_base::out);
                                fstream db_change_into("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\c_database.txt");
                                int len_change_into=0;
                                len_change_into=CountLines("C:\\Users\\Lenovo\\Documents\\cpp\\file\\project-login\\c_database.txt");
                                string change_str_into;
                                for(int i=0;i<len_change_into;i++){
                                    db_change_into>>change_str_into;
                                    db_new_change_pwd<<change_str_into;
                                }
                                cout<<"The password was changed successfully! Please re login!"<<endl;
                                system("pause");
                                main();
                            }
                            //cout<<tmp<<endl;
                        }
                    }
        
                }
                //line_number_0= CountLines(filename);
                //cout<<line_number_0;
            }
        }
        else
            cout<<"ERROR! The username or password is wrong!";
        db.close();
    }
    system("pause");
    return 0;
}